<?php

namespace app\service\DataCollect\YoPoint;

use app\library\DataCollect\YoPointBrand\CargoStruct;
use app\library\DataCollect\YoPointBrand\ConsumerOrderStruct;
use app\library\DataCollect\YoPointBrand\OperatorStruct;
use app\library\DataCollect\YoPointBrand\PlaceVOStruct;
use app\library\DataCollect\YoPointBrand\ProductVOStruct;
use app\library\DataCollect\YoPointBrand\TerminalConfigVOStruct;
use app\library\DataCollect\YoPointBrand\TerminalProductJournalStruct;
use app\library\DataCollect\YoPointBrand\TerminalStruct;
use app\library\DataCollect\YoPointBrand\TerminalVOStruct;
use app\library\DataCollect\YoPointBrand\UserVOStruct;
use app\library\DataReturn;
use app\service\DataCollect\AbstractDataCollectService;
use app\service\DataCollect\InterfaceDataCollectService;
use Exception;
use GuzzleHttp\Exception\GuzzleException;

/**
 * 有朋
 */
class YoPointBrandService extends AbstractDataCollectService implements InterfaceDataCollectService
{

    protected const baseUrl = "https://api.yopoint.com/brand/gateway/index";

    protected const appid = '212246509453';

    protected const appSecret = '1dd8ed4b636cebdd295ae5548ca57a2a';

    /**
     * 初始化Http配置
     * @return array
     */
    protected function initHttpClientConfig(): array
    {
        return [];
    }

    /**
     * api错误返回处理
     * @param $bodyContents
     * @return void
     * @throws Exception
     */
    protected function apiResponseError($bodyContents)
    {
        if (empty($bodyContents)) {
            makeException("返回数据为空");
        }
        $error_code = $bodyContents['error_code'] ?? 0;
        $error_msg = $bodyContents['error_msg'] ?? '';
        if ($error_code !== 0) {
            makeException($error_msg, $error_code);
        }
    }

    /**
     * @param string $method
     * @param array $param
     * @param string $resquestMethod
     * @return DataReturn
     */
    public function requestApi(string $method, array $param = [], string $resquestMethod = "POST"): DataReturn
    {
        $biz_content_json = json_encode($param, JSON_UNESCAPED_UNICODE);
        $params = [
            'appid' => self::appid,
            'biz_content' => $biz_content_json,
            'method' => $method,
            'sign_type' => 'md5',
            'timestamp' => getMillisecondTimestamp(),
            'version' => '1.0.0',
        ];
        $params['sign'] = $this->generateSign($params);
        $options = [
            'json' => $params
        ];
        try {
            if (strtolower($resquestMethod) == "post") {
                $response = $this->httpClient->post(self::baseUrl, $options);
            } else {
                $response = $this->httpClient->get(self::baseUrl, $options);
            }
            $responseContent = $this->responseContent($response);
            return $responseContent;
        } catch (GuzzleException $e) {
            return $this->setError($e->getMessage(), $e->getCode());
        }
    }


    /**
     * 生成签名
     * @param array $params
     * @return string
     */
    protected function generateSign(array $params = []): string
    {
        // 排除sign参数，如果存在
        if (isset($params['sign'])) {
            unset($params['sign']);
        }
        $appSecret = self::appSecret;
        // 按照键名对参数进行字典排序
        ksort($params);
        // 使用 http_build_query 函数生成 URL-encode 之后的请求字符串，并替换掉特殊字符
        $queryStr = urldecode(http_build_query($params));
        // 拼接appSecret
        $strToSign = $queryStr . "&" . $appSecret;
        // 返回md5加密后的字符串，并转换为小写
        return strtolower(md5($strToSign));
    }


    // <editor-fold desc="运营商相关接口">

    /**
     * 运营商列表
     * @param int $page
     * @param int $pageSize
     * @return DataReturn
     */
    public function operatorsList($page = 1, $pageSize = 10): DataReturn
    {
        $method = 'operators.list';
        $param = [
            'page' => $page,
            'pageSize' => $pageSize
        ];
        $res = $this->requestApi($method, $param);
        if ($res->code !== 0) {
            return $res;
        }
        $dataList = &$res->data['data']['data'];

        foreach ($dataList as &$item) {
            $item = OperatorStruct::instance($item);
        }
        //var_export($res);
        /**
         * 'total' => 52,
         * 'per_page' => 10,
         * 'current_page' => 1,
         * 'last_page' => 6,
         * 'from' => 0,
         * 'to' => 10,
         * 'data' => []
         */
        return dataReturn($res->data['data']);
    }

    /**
     * 运营商的增量唯一消费者用户和每日消费用户和累计消费者人数
     * @param $startTime
     * @param $endTime
     */
    public function operatorsCountUser($startTime, $endTime)
    {
        $method = 'operators.count.user';
        $param = [
            'startTime' => $startTime,
            'endTime' => $endTime,
        ];
        $res = $this->requestApi($method, $param);
        var_export($res);
    }


    // </editor-fold>

    // <editor-fold desc="售货机设备相关接口">

    /**
     * 获取设备列表
     * @param int $page
     * @param int $pageSize
     * @param int $updatedAt 大于等于 UpdateAt(时间戳)
     * @param int $activeAt 大于等于 ActiveAt 激活时间(时间戳)
     * @return DataReturn
     */
    public function terminalTerminalList(int $page = 1, int $pageSize = 10, int $updatedAt = 0, int $activeAt = 0): DataReturn
    {
        $method = 'terminal.terminal.list';
        $param = [
            'Page' => $page,
            'PageSize' => $pageSize
        ];
        if ($updatedAt > 0) {
            $param['UpdatedAt'] = $updatedAt;
            $param['ActiveAt'] = $activeAt;
        }
        $res = $this->requestApi($method, $param);
        if ($res->code !== 0) {
            return $res;
        }
        $dataList = &$res->data['data']['data'];

        foreach ($dataList as &$item) {
            foreach ($item['CargoList'] as &$c) {
                $c = CargoStruct::instance($c);
            }
            $item['TerminalConfigVO']['PlaceVO'] = !empty($item['TerminalConfigVO']['PlaceVO']) ? PlaceVOStruct::instance($item['TerminalConfigVO']['PlaceVO']) : null;

            $item['TerminalConfigVO'] = TerminalConfigVOStruct::instance($item['TerminalConfigVO']);
            $item = TerminalStruct::instance($item);
        }

        return dataReturn($res->data['data']);
    }

    /**
     * 根据设备 ID 查询设备
     * @param $tID
     * @return void
     */
    public function terminalTerminalGet($tID)
    {
        $method = 'terminal.terminal.get';
        $param = [
            'TID' => $tID,
        ];
        $res = $this->requestApi($method, $param);
        var_export($res);
    }

    /**
     * 售货机流水记录
     * @param $terminalID
     * @param int $page
     * @param int $pageSize
     * @param string $dateRange 格式 2024-04-06 - 2024-04-12 不要超出31天
     * @return DataReturn
     */
    public function terminalProductJournalList($terminalID, int $page = 1, int $pageSize = 10, string $dateRange = ''): DataReturn
    {
        $method = 'terminal.product.journal.list';
        $param = [
            'Page' => $page,
            'PageSize' => $pageSize,
            'TID' => $terminalID,
        ];
        if (!empty($dateRange)) {
            $param['DateRange'] = $dateRange;
        }
        $res = $this->requestApi($method, $param);
        if ($res->code !== 0) {
            return $res;
        }
        $dataList = &$res->data['data']['data'];

        foreach ($dataList as &$item) {
            $item = TerminalProductJournalStruct::instance($item);
        }
        return dataReturn($res->data['data']);
    }

    /**
     * 分页获取订单信息,交易成功,包括退款的订单,每次返回 20 条记录,
     * 查询的时间是按 UpdatedAt 时间查询,订单状态变更会更新 UpdateAt 时间,第三方需要做排重逻辑
     * @param int $page
     * @param int $startTime 起始 Unix 时间戳
     * @param int $endTime 结束 Unix 时间戳
     */
    public function consumerOrderList(int $page, int $startTime, int $endTime)
    {
        $method = 'consumer.order.list';
        $param = [
            'Page' => $page,
            'StartTime' => $startTime,
            'EndTime' => $endTime,
        ];
        $res = $this->requestApi($method, $param);
        if ($res->code !== 0) {
            return $res;
        }
        $dataList = &$res->data['data']['data'];
        foreach ($dataList as &$item) {
            $item['UserVO'] = UserVOStruct::instance($item['UserVO']);
            $item['ProductVO'] = ProductVOStruct::instance($item['ProductVO']);
            $item['TerminalVO'] = TerminalVOStruct::instance($item['TerminalVO']);
            $item = ConsumerOrderStruct::instance($item);
        }
        return dataReturn($res->data['data']);
    }

    /**
     * 根据订单号(ReceiptNo)获取订单信息
     * @param string $receiptNo
     * @return void
     */
    public function consumerOrderGet(string $receiptNo)
    {
        $method = 'consumer.order.get';
        $param = [
            'ReceiptNo' => $receiptNo,
        ];
        $res = $this->requestApi($method, $param);
        var_export($res);
    }


    // </editor-fold>

    // <editor-fold desc="自取柜相关接口">

    /**
     * 自取柜列表
     * @param $page
     * @param $pageSize
     * @return void
     */
    public function cabinetList($page = 1, $pageSize = 10)
    {
        $method = "cabinet.list";
        $param = [
            'Page' => $page,
            'PageSize' => $pageSize
        ];
        $res = $this->requestApi($method, $param);
        var_export($res);
    }

    /**
     * 获取自取柜设备详情
     * @return void
     */
    public function cabinetGet($cID)
    {
        $method = "cabinet.get";
        $param = [
            "CID" => $cID,
        ];
        $res = $this->requestApi($method, $param);
        var_export($res);
    }


    // </editor-fold>


    public function test()
    {
        $method = "operators.operators.list";
        $param = [
            'page' => 1,
            'pageSize' => 10,
        ];
        $res = $this->requestApi($method, $param);
        var_export($res);
    }


}